package com.apress.gerber.mytest;

import android.app.Activity;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;

import com.apress.gerber.mytest.utils.RawResourceReader;
import com.apress.gerber.mytest.utils.ShaderHelper;
import java.lang.String;import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import com.apress.gerber.mytest.common.MediaPlayerWrapper;

public class IjkPlayerDemoActivity extends Activity implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
    private final String TAG = "GLViewActivity";
    public static final String videoPath = Environment.getExternalStorageDirectory().getPath()+"/one.mp4";
    //private boolean frameAvailable = false;
    int textureParamHandle;
    int textureCoordinateHandle;
    int positionHandle;
    //int textureTranformHandle;
    private int scaleHandle;
    private int aspectHandle;
    private int latHandle;
    private int lonHandle;
    public float g_lat = 0.0f;// 纬度
    public float g_lon = 0.0f;//经度
    /**
     *
     */
    private static float squareSize = 1.0f;
    private static float squareCoords[] = {
            -squareSize, squareSize,  // bottom right
            -squareSize, -squareSize, // top right
            squareSize, -squareSize,  // bottom left
            squareSize, squareSize}; // top left

    private static short drawOrder[] = {0, 1, 2, 0, 2, 3};

    private Context context;

    // Texture to be shown in backgrund
    private FloatBuffer textureBuffer;
    private float textureCoords[] = {
            0.0f, 1.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 1.0f, 0.0f, 1.0f};
    private int[] textures = new int[1];

    private int width, height;

    private int shaderProgram;
    private FloatBuffer vertexBuffer;
    private ShortBuffer drawListBuffer;
    private float[] videoTextureTransform = new float[16];
    private SurfaceTexture videoTexture;
    private GLSurfaceView glView;
    private MediaPlayerWrapper mMediaPlayerWrapper = new MediaPlayerWrapper();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        context = this;
        glView = new GLSurfaceView(this);
        setContentView(glView);
        glView.setEGLContextClientVersion(2);
        glView.setRenderer(this);
        glView.setRenderMode(glView.RENDERMODE_WHEN_DIRTY);
        Log.v(TAG, "videoPath: " + videoPath);

        mMediaPlayerWrapper.init();
        mMediaPlayerWrapper.setPreparedListener(new IMediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(IMediaPlayer mp) {
                cancelBusy();
            }
        });
        mMediaPlayerWrapper.openRemoteFile(videoPath);
        mMediaPlayerWrapper.prepare();
    }

    float startRawX;
    float startRawY;
    float xFlingAngle;
    float xFlingAngleTemp;
    float yFlingAngle;
    float yFlingAngleTemp;
    float PI = 3.1415926535897932384626433832795f;
    @Override
    public boolean onTouchEvent(MotionEvent me) {
        //处理手指滑动事件，我这里的处理是判断手指在横向和竖向滑动的距离
        //这个距离隐射到球体上经度和纬度的距离
        if (me.getAction() == MotionEvent.ACTION_DOWN) {
            Log.v(TAG, "ACTION_DOWN...");
            startRawX = me.getRawX();
            startRawY = me.getRawY();
        } else if (me.getAction() == MotionEvent.ACTION_MOVE) {
            Log.v(TAG, "ACTION_MOVE...");
            float distanceX = startRawX - me.getRawX();
            float distanceY = startRawY - me.getRawY();
            //这里的0.1f是为了不上摄像机移动的过快
            distanceY = 1.0f * (distanceY) / getWindowManager().getDefaultDisplay().getHeight();
            distanceX = 1.0f * (distanceX) / getWindowManager().getDefaultDisplay().getWidth();
            yFlingAngleTemp = distanceY * PI;
            xFlingAngleTemp = distanceX * PI;
            g_lat = (yFlingAngle+yFlingAngleTemp)*180/PI;//得到纬度
            g_lon = (xFlingAngle+xFlingAngleTemp)*180/PI;//得到经度
            Log.v(TAG, "ACTION_MOVE...g_lat: " + g_lat + ", yFlingAngleTemp: " + yFlingAngleTemp + ", distanceY: " + distanceY);
            Log.v(TAG, "ACTION_MOVE...g_lon: " + g_lon + ", xFlingAngleTemp: " + xFlingAngleTemp + ", distanceX: " + distanceX);
        }else if (me.getAction() == MotionEvent.ACTION_UP) {
            Log.v(TAG, "ACTION_UP...");
            xFlingAngle += xFlingAngleTemp;
            yFlingAngle += yFlingAngleTemp;
            if ( yFlingAngle > 2*PI) {
                yFlingAngle = yFlingAngle - PI*2;
            }
            if (yFlingAngle < -2*PI) {
                yFlingAngle = -PI*2 - yFlingAngle;
            }
            if ( xFlingAngle > 2*PI) {
                xFlingAngle = xFlingAngle - PI*2;
            }
            if (xFlingAngle < -2*PI) {
                xFlingAngle = -PI*2 - xFlingAngle;
            }
        }
        return true;
    }

    private void playVideo() {
        Surface surface = new Surface(videoTexture);
        mMediaPlayerWrapper.getPlayer().setSurface(surface);
        surface.release();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if(mMediaPlayerWrapper != null){
            mMediaPlayerWrapper.onPause();
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mMediaPlayerWrapper != null){
            mMediaPlayerWrapper.getPlayer().setSurface(null);
            mMediaPlayerWrapper.onDestroy();
            mMediaPlayerWrapper = null;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMediaPlayerWrapper.onResume();
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        setupGraphics();
        setupVertexBuffer();
        setupTexture();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        this.width = width;
        this.height = height;
        playVideo();
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        videoTexture.updateTexImage();
        videoTexture.getTransformMatrix(videoTextureTransform);

        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        GLES20.glViewport(0, 0, width, height);
        this.drawTexture();

    }

    @Override
    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
        Log.v(TAG, "onFrameAvailable...");
        glView.requestRender();
    }

    private void setupGraphics() {
        final String vertexShader = RawResourceReader.readTextFileFromRawResource(context, R.raw.vetext_sharder);
        final String fragmentShader = RawResourceReader.readTextFileFromRawResource(context, R.raw.fragment_sharder);

        final int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
        final int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
        shaderProgram = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
                new String[]{"texture", "vPosition", "vTexCoordinate", "textureTransform","scale","aspect","g_lat","g_lon"});

        GLES20.glUseProgram(shaderProgram);
        textureParamHandle = GLES20.glGetUniformLocation(shaderProgram, "texture");
        textureCoordinateHandle = GLES20.glGetAttribLocation(shaderProgram, "vTexCoordinate");
        positionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
        //textureTranformHandle = GLES20.glGetUniformLocation(shaderProgram, "textureTransform");

        // scale控制视野范围的缩放。scale约大，视野范围越大，物体缩得越小
        scaleHandle = GLES20.glGetUniformLocation(shaderProgram, "scale");
        // 屏幕宽高比，用于校正纵横比例
        aspectHandle = GLES20.glGetUniformLocation(shaderProgram, "aspect");
        latHandle = GLES20.glGetUniformLocation(shaderProgram, "g_lat");
        lonHandle = GLES20.glGetUniformLocation(shaderProgram, "g_lon");
    }

    private void setupVertexBuffer() {
        // Draw list buffer
        ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);

        // Initialize the texture holder
        ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());

        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);
    }

    private void setupTexture() {
        ByteBuffer texturebb = ByteBuffer.allocateDirect(textureCoords.length * 4);
        texturebb.order(ByteOrder.nativeOrder());

        textureBuffer = texturebb.asFloatBuffer();
        textureBuffer.put(textureCoords);
        textureBuffer.position(0);

        // Generate the actual texture
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glGenTextures(1, textures, 0);
        checkGlError("Texture generate");

        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
        checkGlError("Texture bind");

        videoTexture = new SurfaceTexture(textures[0]);
        videoTexture.setOnFrameAvailableListener(this);
    }

    private void drawTexture() {
        // Draw texture
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);

        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glUniform1i(textureParamHandle, 0);

        GLES20.glUniform1f(scaleHandle, 0.9f);
        GLES20.glUniform1f(aspectHandle, 1.0f);
        GLES20.glUniform1f(latHandle, g_lat);
        GLES20.glUniform1f(lonHandle, g_lon);

        GLES20.glEnableVertexAttribArray(textureCoordinateHandle);
        GLES20.glVertexAttribPointer(textureCoordinateHandle, 4, GLES20.GL_FLOAT, false, 0, textureBuffer);

        //GLES20.glUniformMatrix4fv(textureTranformHandle, 1, false, videoTextureTransform, 0);

        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
        //GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.glDisableVertexAttribArray(textureCoordinateHandle);
    }

    public void checkGlError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e("SurfaceTest", op + ": glError " + GLUtils.getEGLErrorString(error));
        }
    }

    public void cancelBusy(){
        //findViewById(R.id.progress).setVisibility(View.GONE);
    }
}
